﻿using Cysharp.Threading.Tasks;
using IQIGame.Onigao.Framework;
using IQIGame.Onigao.Framework.Serialization;
using IQIGame.Onigao.Logic;
using LFloatMath.Math;
using UnityEngine;

namespace IQIGame.Onigao.GamePlay
{
    public class BattleCommandView_SkillEffective : BaseBattleCommandView<BattleCommand_SkillEffective>
    {
        protected override EBattleUpdateType commandType => EBattleUpdateType.SkillEffective;

        private long partGUID;

#if UNITY_EDITOR
        public override string ToString()
        {
            return base.ToString() + $"[{this.partGUID}]";
        }
#endif

        protected override void OnInitialize(BattleCommand_SkillEffective rCommand, int nExecuterID)
        {
            base.OnInitialize(rCommand, nExecuterID);
            this.partGUID = rCommand.part;
        }

        public override void OnReset()
        {
            base.OnReset();
            this.partGUID = default;
        }

        public override void Free()
        {
            ClassPool.Put(this);
        }

        protected override async UniTask OnPlayUpdate(UnitView unit)
        {
            if (unit == null)
            {
                return;
            }
            await base.OnPlayUpdate(unit);

            var rTimelineComp = unit.GetComponent<BattleTimelineComponent>(ETComponentType.BattleTimelineComponent);
            // 效果比信号点超前，等待
            while ((rTimelineComp.curState == BattleTimelineComponent.ETimelineState.Playing ||
                    rTimelineComp.curState == BattleTimelineComponent.ETimelineState.Pause) &&
                   rTimelineComp.curTimelineSignaleTrigger < this.command.index &&
                   rTimelineComp.curTimelinePart == this.partGUID)
            {
                await UniTask.Yield();
            }
            if (rTimelineComp.curTimelinePart == this.partGUID)
            {
                rTimelineComp.curEffectiveIndex = this.command.index;
            }

            if (rTimelineComp.curTimeline == null)
            {
                return;
            }
            // 在这里播放与目标数量无关的特效来防止受目标数量影响
            var nEffectIndex = rTimelineComp.curEffectiveIndex;
            var rCurInfo = rTimelineComp.curTimeline.effectSignals;
            if (nEffectIndex > rCurInfo.Count - 1)
            {
                LogGame.LogError("技能效果表现未获取到对应信号点，需要补充信号点或检查阻断是否失败");
            }
            ExSignalEmitterData rSignalData = rCurInfo[nEffectIndex];
            var nCmdGUID = this.command.responseGUID;
            if (rSignalData.type == EExSignalType.SkillEffect)
            {
                var rSignalType = rSignalData.paramInt?.Length > 0 ? (ESignalSkillEffectType)rSignalData.paramInt[0] : ESignalSkillEffectType.Normal;
                var rStrArr = rSignalData.paramStr;
                var rIntArr = rSignalData.paramInt;
                var rBoolArr = rSignalData.paramBool;

                var rAttacker = unit;
                if (rSignalType == ESignalSkillEffectType.Delay)
                {
                    var nDummy = rIntArr.Get(1);
                    if (nDummy == -1) //  =-1 时认为是向输入的选中点发送特效
                    {
                        var rTargetEffect = rStrArr.Get(0);
                        if (!string.IsNullOrEmpty(rTargetEffect))
                        {
                            var rAttackerEffectComp = rAttacker.GetComponent<EffectComponent>(ETComponentType.EffectComponent);
                            rAttackerEffectComp.AddTimelineEffect(rTargetEffect, rTimelineComp.curPartTargetPos.ToVector3XZ(), false);
                        }
                    }
                }
                else if (rSignalType == ESignalSkillEffectType.Bullet)
                {
                    // 指向目标点的子弹在这里发射来保证只发一发
                    var nTargetDummy = rIntArr.Get(2);
                    if (nTargetDummy < 0)
                    {
                        var rBulletComp = unit.GetComponent<BulletComponent>(ETComponentType.BulletComponent);
                        var rStartDeviation = new Vector3(rIntArr.Get(4) / 100f, rIntArr.Get(5) / 100f, rIntArr.Get(6) / 100f);
                        var rEndDeviation = new Vector3(rIntArr.Get(7) / 100f, rIntArr.Get(8) / 100f, rIntArr.Get(9) / 100f);
                        var nEffectRandomCount = rIntArr.Get(10);
                        var rEffectName = rStrArr.Get(0);
                        if (nEffectRandomCount > 1)
                        {
                            var nBulletEffectIndex = BattleManager.Instance.ctrl.data.random.Range(0, nEffectRandomCount);
                            rEffectName = rStrArr.Get(nBulletEffectIndex);
                        }
                        rBulletComp.AddBulletToPos(rEffectName, rIntArr.Get(1),
                            rStartDeviation, rEndDeviation,
                            rTimelineComp.curPartTargetPos.ToVector3XZ(),
                            rIntArr.Get(3) / 1000f,
                            () =>
                            {
                                // this.Action(rAttacker, rDefender, rCommandData).Forget();
                                BattleManager.Instance.ctrl?.queueCtrl.OnWaitComplete(nCmdGUID).Forget();
                            });
                        BattleManager.Instance.ctrl?.queueCtrl.AddWaitingQueue(nCmdGUID);
                    }
                }
            }
        }
    }

    // 效果开始表现 不进行等待，按需执行发射逻辑
    public class BattleCommandView_SkillEffectiveStart : BaseBattleCommandView<BattleCommand_SkillEffectiveStart>
    {
        protected override EBattleUpdateType commandType => EBattleUpdateType.SkillEffectiveStart;
#if UNITY_EDITOR
        public override string ToString()
        {
            return $"{base.ToString()}, [{this.command.partGUID}] response:{this.command.responseGUID}, data:{this.command.data?.pod}";
        }
#endif

        public override void Free()
        {
            ClassPool.Put(this);
        }

        protected override async UniTask OnPlayUpdate(UnitView unit)
        {
            await base.OnPlayUpdate(unit);

            var rBattleData = BattleManager.Instance.ctrl.data;
            // 仅本skilleffective对应的timeline才会考虑技能效果的发射阶段
            var rTimelineComp = unit.GetComponent<BattleTimelineComponent>(ETComponentType.BattleTimelineComponent);
            if (rTimelineComp.curTimelinePart != this.command.partGUID)
            {
                return;
            }

            var rCommandData = this.command.data?.pod;
            switch (rCommandData)
            {
                case ImpactResponse rImpact:
                {
                    // 启动冲锋，冲锋的技能结果由回调完成
                    var rImpactComp = unit.GetComponent<BattleImpactComponent>(ETComponentType.BattleImpactComponent);
                    rImpactComp.Impact(rImpact.targetPos, rImpact.speed, rImpact.aspect).Forget();
                    break;
                }
                case TotemResponse rTotem:
                {
                    var rSummoner = rBattleData.GetUnit(rTotem.summonerGuid);
                    var rTotemView = UnitViewFactory.CreateBattleTotemView(rTotem, unit.teamIndex,rSummoner);
                    rTotemView.InitializeView().Forget();
                    rBattleData.AddUnit(rTotemView);
                    break;
                }
            }

#region 执行发射逻辑

            var rQueueCtrl = BattleManager.Instance.ctrl.queueCtrl;
            var rAttacker = unit;
            var rDefender = rBattleData.GetUnit(this.command.targetID);
            var rSignalType = ESignalSkillEffectType.Normal;
            string[] rStrArr = null;
            int[] rIntArr = null;
            bool[] rBoolArr = null;
            var nCmdGUID = this.command.responseGUID;
            if (rTimelineComp.curTimeline != null)
            {
                var nEffectIndex = rTimelineComp.curEffectiveIndex;
                var rCurInfo = rTimelineComp.curTimeline.effectSignals;
                if (rCurInfo.Count > nEffectIndex)
                {
                    ExSignalEmitterData rSignalData = rCurInfo[nEffectIndex];
                    if (rSignalData != null) // 有信号点
                    {
                        rSignalType = rSignalData.paramInt?.Length > 0 ? (ESignalSkillEffectType)rSignalData.paramInt[0] : ESignalSkillEffectType.Normal;
                        rStrArr = rSignalData.paramStr;
                        rIntArr = rSignalData.paramInt;
                        rBoolArr = rSignalData.paramBool;
                    }
                }
            }
            switch (rSignalType)
            {
                case ESignalSkillEffectType.Normal:
                {
                }
                    break;
                case ESignalSkillEffectType.Bullet:
                {
                    // 有目标单位的子弹在这里发射，每个目标都有一发
                    var nTargetDummy = rIntArr.Get(2);
                    if (nTargetDummy >= 0)
                    {
                        var rBulletComp = unit.GetComponent<BulletComponent>(ETComponentType.BulletComponent);
                        var rStartDeviation = new Vector3(rIntArr.Get(4) / 100f, rIntArr.Get(5) / 100f, rIntArr.Get(6) / 100f);
                        var rEndDeviation = new Vector3(rIntArr.Get(7) / 100f, rIntArr.Get(8) / 100f, rIntArr.Get(9) / 100f);
                        var nEffectRandomCount = rIntArr.Get(10);
                        var rEffectName = rStrArr.Get(0);
                        if (nEffectRandomCount > 1)
                        {
                            var nEffectIndex = BattleManager.Instance.ctrl.data.random.Range(0, nEffectRandomCount);
                            rEffectName = rStrArr.Get(nEffectIndex);
                        }
                        rBulletComp.AddBulletToTarget(rEffectName, rIntArr.Get(1),
                            rStartDeviation, rEndDeviation, rDefender, nTargetDummy,
                            rIntArr.Get(3) / 1000f,
                            () =>
                            {
                                // this.Action(rAttacker, rDefender, rCommandData).Forget();
                                BattleManager.Instance.ctrl?.queueCtrl.OnWaitComplete(nCmdGUID).Forget();
                            });
                        rQueueCtrl.AddWaitingQueue(nCmdGUID);
                    }
                }
                    break;
                case ESignalSkillEffectType.Delay:
                {
                    var nDummy = rIntArr.Get(1);
                    if (nDummy >= 0) //  < 0时认为是向特定点发送特效 >=0特效播放在目标单位骨骼点上
                    {
                        var rTargetEffect = rStrArr.Get(0);
                        if (!string.IsNullOrEmpty(rTargetEffect))
                        {
                            var rAttackerEffectComp = rAttacker.GetComponent<EffectComponent>(ETComponentType.EffectComponent);
                            var rDefenderEffectComp = rDefender.GetComponent<EffectComponent>(ETComponentType.EffectComponent);
                            var rEffectPath = rAttackerEffectComp.GetRoleEffectPath(rTargetEffect);
                            var rBindComp = rDefender.GetComponent<BattleViewBindPointComponent>(ETComponentType.BattleViewBindPointComponent);
                            rDefenderEffectComp.AddTimelineEffectWithPath(rEffectPath, nDummy, EVFXSpace.Local, false, 0, false, rBindComp, Vector3.zero);
                        }
                    }
                    var nDelay = rIntArr.Get(2);
                    if (nDelay > 0)
                    {
                        BattleClientUtil.DelayInvoke(nDelay, () =>
                        {
                            // this.Action(rAttacker, rDefender, rCommandData).Forget();
                            BattleManager.Instance.ctrl?.queueCtrl.OnWaitComplete(nCmdGUID).Forget();
                        }).Forget();
                        rQueueCtrl.AddWaitingQueue(nCmdGUID);
                    }
                    break;
                }
                case ESignalSkillEffectType.WaitCallback:
                {
                    var rKey = rStrArr.Get(0);
                    if (!string.IsNullOrEmpty(rKey))
                    {
                        rTimelineComp.AddWaitingQueue(rKey, this.command.responseGUID);
                    }
                    break;
                }
            }

#endregion
        }
    }

    // 效果结算表现
    public class BattleCommandView_SkillEffectiveEnd : BaseBattleCommandView<BattleCommand_SkillEffectiveEnd>
    {
        protected override EBattleUpdateType commandType => EBattleUpdateType.SkillEffectiveEnd;

#if UNITY_EDITOR
        public override string ToString()
        {
            return $"{base.ToString()}, response:{this.command.responseGUID}, data:{this.command.data?.pod}";
        }
#endif

        public override void Free()
        {
            ClassPool.Put(this);
        }

        protected override async UniTask OnPlayUpdate(UnitView unit)
        {
            if (unit == null)
            {
                return;
            }

            await base.OnPlayUpdate(unit);

            var rCommandData = this.command.data?.pod;
            var rAttacker = unit;
            await this.Action(rAttacker, rCommandData);
        }

        private async UniTask Action(UnitView unit, ISerializeCustomPOD rData)
        {
            if (BattleManager.Instance.ctrl == null || rData == null)
            {
                return;
            }
            var rBattleData = BattleManager.Instance.ctrl.data;
            switch (rData)
            {
                case DamageResponse rDamage:
                {
                    var rTarget = rBattleData.GetUnit(rDamage.defender);
                    this.OnHit(rDamage, unit, rTarget);
                    break;
                }
                case CureResponse rCure:
                {
                    // 冒字
                    MsgDispatcher.Broadcast(MsgEventType.BattleView_TakeCure, rCure);
                    break;
                }
                // 子类放在父类上面
                case TotemResponse rTotem:
                {
                    if (rTotem.packageResp != null)
                    {
                        for (int i = 0; i < rTotem.packageResp.Count; i++)
                        {
                            for (int j = 0; j < rTotem.packageResp[i].packageResps.Count; j++)
                            {
                                var rResp = rTotem.packageResp[i].packageResps[j]?.resp?.pod;
                                if (rResp != null)
                                {
                                    await this.Action(unit, rResp);
                                }
                            }
                        }
                    }
                    break;
                }
                case SummonResponse rSummon:
                {
                    var rUnit = UnitViewFactory.CreateBattleUnitView(rSummon.unit, unit.teamIndex);
                    rBattleData.AddUnit(rUnit);

                    // 特殊属性会有修改属性update同步
                    await rUnit.InitializeView();
                    rUnit.GetComponent<UnitViewComponent>(ETComponentType.UnitViewComponent).Enable();
                    break;
                }
                case SkillEffectivePackageResponse rPackage:
                {
                    for (int i = 0; i < rPackage.packageResps.Count; i++)
                    {
                        var rResp = rPackage.packageResps[i]?.resp?.pod;
                        if (rResp != null)
                        {
                            await this.Action(unit, rResp);
                        }
                    }
                    break;
                }
                case ImpactResponse rImpact:
                {
                    // 冲撞的结果 可能未撞到目标无效果
                    if (rImpact.packageResp != null)
                    {
                        for (int i = 0; i < rImpact.packageResp.packageResps.Count; i++)
                        {
                            var rResp = rImpact.packageResp.packageResps[i]?.resp?.pod;
                            if (rResp != null)
                            {
                                await this.Action(unit, rResp);
                            }
                        }
                    }
                    break;
                }
            }
            (rData as IReusableClassWithFree)?.Free();
        }

        private void OnHit(DamageResponse rDamage, UnitView rAttacker, UnitView rDefender)
        {
            if (!rDamage.dodge && rDefender != null)
            {
                // 动作
                var rViewComp = rDefender.GetComponent<UnitViewComponent>(ETComponentType.UnitViewComponent);
                rViewComp.OnHit();
                // 受击特效
                var rHitEffect = rAttacker.GetComponent<EffectComponent>(ETComponentType.EffectComponent).GetHitEffectBySkill(rDamage.damageType, rDamage.configID);
                var rEffectComp = rDefender.GetComponent<EffectComponent>(ETComponentType.EffectComponent);
                rEffectComp.AddHitEffect(rHitEffect);
            }
            // 冒字
            MsgDispatcher.Broadcast(MsgEventType.BattleView_TakeDamage, rDamage);
        }
    }

    public class BattleCommandView_SkillEffectiveResponse : BaseBattleCommandView<BattleCommand_SkillEffectiveResponse>
    {
    }
}